package comunicating.classes;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Calendar;
import java.util.HashMap;

import util.FileToBigException;
import util.IO;


import noncomunicating.classes.*;

public class ServerLoop{
	public static boolean verbose = false;
	public static String directory = "/"; 
	private static byte[] notFoundPage, controlPage;
	private static int port = 80;
	private static boolean continueLoop = true;
	private static ServerSocket server = null;
	private static Calendar time;
	private static long upSince;
	private static String password = "default";
	/**
	 * @param args
	 */
	
	private static void setTimes(){
		time = Calendar.getInstance();
		upSince = time.getTimeInMillis();
	}
	
	public static String getTimeString(){	
		return time.getTime().toString();
	}
	
	public static long getUpSince() {
		return upSince;
	}

	private static void shutdown(){ //XXX this is an AWFUL way of ending the loop I should fix it
		continueLoop = false;			//I don't know how to fix this
		try {
			server.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		
		try {
			controlPage = IO.getFileBytes("control.ctr");
			notFoundPage = IO.getFileBytes("404.htm");
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		} catch (FileToBigException e) {
			e.printStackTrace();
		}
		
		loadSettings(args);
		
			System.out.println("verbose: " + verbose + "\nDirectory: "
					+ directory + "\n\n");
		
		try {
			server = new ServerSocket(port);
		} catch (IOException e) {
			System.err.println("Failed to establish server socket.");
			e.printStackTrace();
		}
		
		setTimes();
		
		while(continueLoop){
			try {
				Socket clientSocket = server.accept();
				new Request(clientSocket).start();
			} 
			catch (SocketException e){ //XXX I handled this to make up for my shitty way of ending the loop
				if(continueLoop){
					System.err.println("THIS ERROR IS NOT PPART OF THE SHUT DOWN SEQUENCE.");
					e.printStackTrace();
				}
				else{
					System.err.println("ServerSocket has been closed it appears that this is part of the shutdown sequence");
					break;
				}
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void loadSettings(String[] args){
		for(int c = 0; c < args.length; c++){
			if(args[c].equalsIgnoreCase("-d")){
				c++;
				directory = args[c];
			}
			else if(args[c].equalsIgnoreCase("-v")){
				verbose = true;
			}
			else if (args[c].equalsIgnoreCase("-p")){
				c++;
				port = Integer.parseInt(args[c]);
			}
			else if (args[c].equalsIgnoreCase("-pw")){
				c++;
				password = args[c];
			}
			else if (args[c].equalsIgnoreCase("-nf")){
				c++;
				try {
					notFoundPage = IO.getFileBytes(args[c]);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (FileToBigException e) {
					e.printStackTrace();
				}
				
			}
		}
	}
	
	public static boolean doPasswordsMatch(String pw){
		return password.equals(pw);
	}
	
	public static void liveLoadSettings(HashMap<String, String> modifiers){
		if (modifiers.containsKey("password") && modifiers.get("password").equals(password)) {
			if (modifiers.containsKey("directory")) {
				String dir = modifiers.get("directory").replace("%2F", "/");
				dir = dir.replace("%3A", ":");
				dir = dir.replace("%5C", "/"); //%5C is actually backslash but this is more convenient
				directory = dir;
				System.out.println("###Directory: " + directory);
			}
			if (modifiers.containsKey("verbose")) {
				if (modifiers.get("verbose").equalsIgnoreCase("on")) {
					verbose = true;
				} else {
					verbose = false;
				}
				System.out.println("###Verbose: " + verbose);
			}
			if (modifiers.containsKey("shutdown")) {
				if (modifiers.get("shutdown").equals("true")) {
					shutdown();
					System.out.println("### Shutting Down ###");
				}

			}
		}
	}

	public static byte[] getNotFoundPage() {
		return notFoundPage;
	}

	public static byte[] getControlPage() {
		return controlPage;
	}

	public static int getPort() {
		return port;
	}

}
